跳到主要内容

Java 泛型

Java 的类型擦除

Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。

Java 的泛型是伪泛型,这是因为 Java 在编译期间,所有的泛型信息都会被擦掉,这也就是通常所说类型擦除 。

如下例子:

List<Integer> list = new ArrayList<>();

list.add(12);
//这里直接添加会报错
list.add("a");

//但是通过反射添加,是可以的
Class<? extends List> clazz = list.getClass();
Method add = clazz.getDeclaredMethod("add", Object.class);
add.invoke(list, "kl");

System.out.println(list);

输出:

泛型各种字母的含义

平时使用泛型时会发现有很多种字母,其实这些字母不是乱取的,一般使用以下规范

  • T 意味某种类型
  • E 意味 链表、数组里的元素,如 List list 表示 list 里的元素。
  • K 意味 Map(k,v) 里的键值 Key
  • V 意味 返回或映射的值。

泛型的运用要受到如下限制 :

  • 不能使用基本类型的类型参数,可以使用其包装类型代替。
  • 静态成员无法使用类型参数。
  • 不能使用泛型类异常
  • 不能实例化泛型对象或数组 T t = new T(); T[] a=new T

上\下界通配符

注意比较特殊的是这个 ? 通配符,它表示不限定类型

List<?> // 表示可以存任何类型

// 下界通配符(? super)
List<? super A> // 意思是 List 集合,它可以持有 A 及其父类的实例。

// 上界通配符()
List<? extends A> // 可以包含 A及其子类

Java 的静态泛型方法

private static <T extends Comparable> T max(T t1, T t2) {
return t1.compareTo(t2) > 0 ? t1 : t2;
}

Java 的泛型类

//在实例化泛型类时,必须指定T的具体类型
public class Generic<T> {

private T key;

public Generic(T key) {
this.key = key;
}

public T getKey() {
return key;
}
}

如何实例化泛型类:

Generic<Integer> genericInteger = new Generic<Integer>(123456);

Java 的泛型接口

public interface Generator<T> {
public T method();
}

实现泛型接口,不指定类型:

class GeneratorImpl<T> implements Generator<T>{
@Override
public T method() {
return null;
}
}

实现泛型接口,指定类型:

class GeneratorImpl implements Generator<String>{
@Override
public String method() {
return "hello";
}
}